ci(scripts): keep every released image public on Docker Hub - #2303
Conversation
Docker Hub creates a repository on first push with the organization's default visibility, which is private, and the shared release pipeline never changes it. midaz-tracer, midaz-tracer-migrations and midaz-ledger-migrations therefore shipped 4.0.0-beta.x unpullable, so an anonymous helm install of the midaz chart ImagePullBackOffs on every v4 component. Add a dockerhub-visibility workflow that pre-creates the release images as public and flips any that are private, gate the release pipeline on it so a new image never exists private, and make it workflow_dispatch-able to repair the repositories that already went out private. The image list is derived from gitops_yaml_key_mappings, the pipeline's own registry of published images, so it cannot drift from what is actually pushed. Co-authored-by: Codesmith <codesmith-bot@users.noreply.github.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (4)
📝 WalkthroughWalkthroughThe change adds Docker Hub visibility enforcement. A reusable workflow runs the script before the release pipeline. The script discovers mapped images, authenticates with Docker Hub, and creates or updates repositories as public. The ChangesDocker Hub visibility enforcement
Dependency version update
Sequence Diagram(s)sequenceDiagram
participant ReleasePipeline
participant DockerHubVisibilityWorkflow
participant VisibilityScript
participant DockerHubAPI
ReleasePipeline->>DockerHubVisibilityWorkflow: invoke visibility job
DockerHubVisibilityWorkflow->>VisibilityScript: run with Docker Hub credentials
VisibilityScript->>DockerHubAPI: authenticate and obtain token
VisibilityScript->>DockerHubAPI: inspect mapped image repositories
VisibilityScript->>DockerHubAPI: create or update repositories as public
VisibilityScript-->>DockerHubVisibilityWorkflow: return aggregate status
DockerHubVisibilityWorkflow-->>ReleasePipeline: continue after successful check
✨ Finishing Touches✨ Simplify code
Comment |
|
| Library | Current | Latest | Status |
|---|---|---|---|
lib-auth/v3 |
v3.3.0 |
v3.3.0 |
✅ Current |
lib-commons/v6 |
v6.7.0 |
v6.7.0 |
✅ Current |
lib-observability/v2 |
v2.1.1 |
v2.1.1 |
✅ Current |
lib-service-discovery |
v1.1.0 |
v1.1.0 |
✅ Current |
lib-streaming/v2 |
v2.0.0 |
skipped | ⏭️ Skipped — ignore file, expires 2026-08-17 · why? |
✅ 4 current · 🔴 0 needs update · 🕒 0 in grace · ⏭️ 1 skipped ·
🔍 PR Validation Summary✅ PR Mergeable — no blocking failures
|
Co-authored-by: Codesmith <codesmith-bot@users.noreply.github.com>
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
🔒 Security Scan Results —
|
| Stage | Status | Blocking? |
|---|---|---|
| Filesystem Scan | ✅ Clean | — |
| Docker Image Scan | ✅ Clean | — |
| Docker Hub Health Score | ✅ Clean | — |
| Pre-release Version Check | ✅ Clean | — |
Trivy
Filesystem Scan
✅ No vulnerabilities or secrets found.
Docker Image Scan
✅ No vulnerabilities found.
Docker Hub Health Score Compliance
✅ Policies — 4/4 met
| Policy | Status |
|---|---|
| Default non-root user | ✅ Passed |
| No fixable critical/high CVEs | ✅ Passed |
| No high-profile vulnerabilities | ✅ Passed |
| No AGPL v3 licenses | ✅ Passed |
Pre-release Version Check
✅ No unstable version pins found.
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/dockerhub-visibility.yml:
- Around line 8-18: Add a workflow-level concurrency group to serialize
ensure-public runs across release and manual dispatches, using cancellation
behavior appropriate for preserving the active repository mutation. Set a finite
timeout-minutes on the ensure-public job, and keep the existing job behavior
unchanged.
In @.github/workflows/release.yml:
- Around line 21-23: Update the dockerhub-visibility reusable workflow
invocation to replace secrets: inherit with an explicit secrets mapping for
DOCKER_USERNAME and DOCKERHUB_IMAGE_PUSH_TOKEN, and add matching required secret
declarations to the called workflow’s workflow_call configuration. Preserve
direct secret access for workflow_dispatch runs.
In `@scripts/ensure-dockerhub-public.sh`:
- Around line 73-80: Update the TOKEN login request in the Docker Hub
authentication flow to use the existing hub_call retry and timeout policy,
including protection against stalled connections and retries for transient 5xx
responses. Preserve the current JSON request payload and token extraction
behavior, and keep the existing failure handling when no token is returned.
- Around line 91-102: Update the HTTP 200 response handling around the
is_private jq lookup so a missing, null, or otherwise unreadable visibility
field sets failed=1 and exits that verification path without reporting the
repository as already public. Only print “already public” when is_private is
explicitly false, while preserving the existing PATCH flow for an explicit true
value.
- Around line 41-56: Update the retry loop in ensure-dockerhub-public.sh to
capture curl’s exit code separately instead of appending a second “000” to the
HTTP status, and route any nonzero curl result through the existing retry
branch. Add --connect-timeout and --max-time to both curl invocations,
preserving the current retry behavior for HTTP 5xx responses.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: b84c425b-5782-468c-aace-02e80b9582f3
📒 Files selected for processing (3)
.github/workflows/dockerhub-visibility.yml.github/workflows/release.ymlscripts/ensure-dockerhub-public.sh
📊 Unit Test Coverage Report:
|
| Metric | Value |
|---|---|
| Overall Coverage | 86.5% ✅ PASS |
| Threshold | 80% |
Coverage by Package
| Package | Coverage |
|---|---|
github.com/LerianStudio/midaz/v4/components/tracer/internal/adapters/cel |
84.2% |
github.com/LerianStudio/midaz/v4/components/tracer/internal/adapters/grpc/in |
83.1% |
github.com/LerianStudio/midaz/v4/components/tracer/internal/adapters/http/in/middleware |
84.4% |
github.com/LerianStudio/midaz/v4/components/tracer/internal/adapters/http/in |
88.7% |
github.com/LerianStudio/midaz/v4/components/tracer/internal/adapters/postgres/db |
81.5% |
github.com/LerianStudio/midaz/v4/components/tracer/internal/adapters/postgres |
86.4% |
github.com/LerianStudio/midaz/v4/components/tracer/internal/adapters/seamtenant |
84.4% |
github.com/LerianStudio/midaz/v4/components/tracer/internal/observability |
74.3% |
github.com/LerianStudio/midaz/v4/components/tracer/internal/services/cache |
91.8% |
github.com/LerianStudio/midaz/v4/components/tracer/internal/services/command |
90.2% |
github.com/LerianStudio/midaz/v4/components/tracer/internal/services/metrics |
58.5% |
github.com/LerianStudio/midaz/v4/components/tracer/internal/services/query |
79.3% |
github.com/LerianStudio/midaz/v4/components/tracer/internal/services/workers |
82.7% |
github.com/LerianStudio/midaz/v4/components/tracer/internal/services |
60.3% |
github.com/LerianStudio/midaz/v4/components/tracer/internal/testhelper |
0.0% |
github.com/LerianStudio/midaz/v4/components/tracer/pkg/clock |
50.0% |
github.com/LerianStudio/midaz/v4/components/tracer/pkg/contextutil |
100.0% |
github.com/LerianStudio/midaz/v4/components/tracer/pkg/hash |
100.0% |
github.com/LerianStudio/midaz/v4/components/tracer/pkg/logging |
100.0% |
github.com/LerianStudio/midaz/v4/components/tracer/pkg/migration |
89.0% |
github.com/LerianStudio/midaz/v4/components/tracer/pkg/model |
93.0% |
github.com/LerianStudio/midaz/v4/components/tracer/pkg/net/http |
91.7% |
github.com/LerianStudio/midaz/v4/components/tracer/pkg/resilience |
97.8% |
github.com/LerianStudio/midaz/v4/components/tracer/pkg/sanitize |
87.1% |
github.com/LerianStudio/midaz/v4/components/tracer/pkg/validation |
50.0% |
github.com/LerianStudio/midaz/v4/components/tracer/pkg |
90.9% |
Generated by Go PR Analysis workflow
📊 Unit Test Coverage Report:
|
| Metric | Value |
|---|---|
| Overall Coverage | 85.4% ✅ PASS |
| Threshold | 80% |
Coverage by Package
| Package | Coverage |
|---|---|
github.com/LerianStudio/midaz/v4/components/ledger/cmd/backfill |
0.0% |
github.com/LerianStudio/midaz/v4/components/ledger/internal/adapters/http/in |
84.4% |
github.com/LerianStudio/midaz/v4/components/ledger/internal/adapters/mongodb/fees |
35.7% |
github.com/LerianStudio/midaz/v4/components/ledger/internal/adapters/mongodb/onboarding |
66.7% |
github.com/LerianStudio/midaz/v4/components/ledger/internal/adapters/mongodb/transaction |
66.7% |
github.com/LerianStudio/midaz/v4/components/ledger/internal/adapters/postgres/account |
100.0% |
github.com/LerianStudio/midaz/v4/components/ledger/internal/adapters/postgres/accounttype |
66.7% |
github.com/LerianStudio/midaz/v4/components/ledger/internal/adapters/postgres/asset |
100.0% |
github.com/LerianStudio/midaz/v4/components/ledger/internal/adapters/postgres/assetrate |
100.0% |
github.com/LerianStudio/midaz/v4/components/ledger/internal/adapters/postgres/balance |
97.5% |
github.com/LerianStudio/midaz/v4/components/ledger/internal/adapters/postgres/ledger |
100.0% |
github.com/LerianStudio/midaz/v4/components/ledger/internal/adapters/postgres/operation |
90.7% |
github.com/LerianStudio/midaz/v4/components/ledger/internal/adapters/postgres/operationroute |
100.0% |
github.com/LerianStudio/midaz/v4/components/ledger/internal/adapters/postgres/organization |
100.0% |
github.com/LerianStudio/midaz/v4/components/ledger/internal/adapters/postgres/portfolio |
100.0% |
github.com/LerianStudio/midaz/v4/components/ledger/internal/adapters/postgres/readseam |
94.5% |
github.com/LerianStudio/midaz/v4/components/ledger/internal/adapters/postgres/segment |
100.0% |
github.com/LerianStudio/midaz/v4/components/ledger/internal/adapters/postgres/transaction |
96.6% |
github.com/LerianStudio/midaz/v4/components/ledger/internal/adapters/postgres/transactionroute |
100.0% |
github.com/LerianStudio/midaz/v4/components/ledger/internal/adapters/rabbitmq |
88.8% |
github.com/LerianStudio/midaz/v4/components/ledger/internal/adapters/redis/transaction/balance |
99.0% |
github.com/LerianStudio/midaz/v4/components/ledger/internal/adapters/tracer |
72.2% |
github.com/LerianStudio/midaz/v4/components/ledger/internal/crm/adapters/mongodb/audit |
71.4% |
github.com/LerianStudio/midaz/v4/components/ledger/internal/crm/adapters/mongodb/dupkey |
91.7% |
github.com/LerianStudio/midaz/v4/components/ledger/internal/crm/adapters/mongodb/encryption |
100.0% |
github.com/LerianStudio/midaz/v4/components/ledger/internal/crm/adapters/mongodb/holder |
73.8% |
github.com/LerianStudio/midaz/v4/components/ledger/internal/crm/adapters/mongodb/instrument |
67.4% |
github.com/LerianStudio/midaz/v4/components/ledger/internal/crm/services/encryption |
94.4% |
github.com/LerianStudio/midaz/v4/components/ledger/internal/crm/services |
95.4% |
github.com/LerianStudio/midaz/v4/components/ledger/internal/services/backfill |
73.8% |
github.com/LerianStudio/midaz/v4/components/ledger/internal/services/command |
86.7% |
github.com/LerianStudio/midaz/v4/components/ledger/internal/services/composition |
84.1% |
github.com/LerianStudio/midaz/v4/components/ledger/internal/services/fees/midaz |
100.0% |
github.com/LerianStudio/midaz/v4/components/ledger/internal/services/fees |
88.9% |
github.com/LerianStudio/midaz/v4/components/ledger/internal/services/query |
91.8% |
github.com/LerianStudio/midaz/v4/components/ledger/internal/services |
0.0% |
github.com/LerianStudio/midaz/v4/components/ledger/pkg/fee |
97.7% |
github.com/LerianStudio/midaz/v4/components/ledger/pkg/feeshared/bsondecimal |
100.0% |
github.com/LerianStudio/midaz/v4/components/ledger/pkg/feeshared/model |
95.3% |
github.com/LerianStudio/midaz/v4/components/ledger/pkg/feeshared/nethttp |
96.0% |
github.com/LerianStudio/midaz/v4/components/ledger/pkg/readrouting |
100.0% |
Generated by Go PR Analysis workflow
🔒 Security Scan Results —
|
| Stage | Status | Blocking? |
|---|---|---|
| Filesystem Scan | ✅ Clean | — |
| Docker Image Scan | ✅ Clean | — |
| Docker Hub Health Score | ✅ Clean | — |
| Pre-release Version Check | ✅ Clean | — |
Trivy
Filesystem Scan
✅ No vulnerabilities or secrets found.
Docker Image Scan
✅ No vulnerabilities found.
Docker Hub Health Score Compliance
✅ Policies — 4/4 met
| Policy | Status |
|---|---|
| Default non-root user | ✅ Passed |
| No fixable critical/high CVEs | ✅ Passed |
| No high-profile vulnerabilities | ✅ Passed |
| No AGPL v3 licenses | ✅ Passed |
Pre-release Version Check
✅ No unstable version pins found.
Co-authored-by: Codesmith <codesmith-bot@users.noreply.github.com>
Co-authored-by: Codesmith <codesmith-bot@users.noreply.github.com>
Description
Docker Hub creates a repository on first push using the organization's default visibility, which is private, and the shared release pipeline never changes it. So an image is public only if someone remembered to flip it by hand, and the v4 images nobody flipped went out unpullable:
4.0.0-beta.24)lerianstudio/midaz-ledgerlerianstudio/midaz-tracerdenied/unauthorizedlerianstudio/midaz-tracer-migrationsdenied/unauthorizedlerianstudio/midaz-ledger-migrationsdenied/unauthorizedThat breaks an anonymous
helm installof the midaz chart on every v4 component: the ledger pulls, its migration Job and the whole tracer surfaceImagePullBackOff.This adds a
dockerhub-visibilityworkflow that ensures each released repository exists and is public, and gates the release pipeline on it so a new image never exists private in the first place:scripts/ensure-dockerhub-public.shdoes the work: pre-create missing repositories withis_private: false,PATCHexisting private ones, no-op on public ones, and fail the job if any repository is still private at the end. It authenticates with theDOCKER_USERNAME/DOCKERHUB_IMAGE_PUSH_TOKENpair the build already uses, and retries transport errors and 5xx so a flaky Docker Hub cannot fail a release on its own.The image list is not a second hardcoded copy: it is derived from
gitops_yaml_key_mappings, the pipeline's own registry of published images, so it cannot drift from what actually gets pushed.The workflow is also
workflow_dispatch-able, so once this lands ondevelopa single manual run repairs the three repositories that already went out private, without waiting for the next release.One prerequisite worth confirming before merge:
DOCKERHUB_IMAGE_PUSH_TOKENmust be allowed to change repository settings, not only push tags. If it is push-only, the job fails loudly with the offending repository and HTTP status instead of silently leaving an image private.Type of Change
ci: CI pipeline or workflow changesBreaking Changes
None. No Go code, no image contents, no tags change; only the visibility of the repositories the pipeline publishes to.
Testing
actionlintandshellcheckare clean on the new workflow and script. The script was exercised against a stubbed Docker Hub covering every branch: already-public no-op, private repository flipped, missing repository created,PATCHdenied (403), login failure, unreadable mapping, and a503that retries three times and then fails.Related Issues
Blocks the midaz v4 Helm work in LerianStudio/helm#1838, which cannot ship a working default install while these three images are private.